package rs.etf.mips.crossroad.logic.lightcontrol;

import rs.etf.mips.crossroad.logic.Crossroad;
import rs.etf.mips.crossroad.logic.Light;
import rs.etf.mips.crossroad.logic.Line;
import rs.etf.mips.crossroad.logic.PedestrianSemaphore;
import rs.etf.mips.crossroad.logic.PedestrianSemaphore.State;
import rs.etf.mips.crossroad.logic.StreetDirection;

public class LightStateHorizontalForward extends LightState {

	LightStateHorizontalForward(Crossroad crossroad, long initCounter) {
		super(crossroad, initCounter);
	}

	@Override
	public LightState nextState() {
		this.setArrivals(Direction.Vertical, false);
		return LightStateFactory.instance().getLightState(
				LightStateDescriptor.VerticalLeftRight);
	}

	@Override
	protected void updateCrossroadLights() {

		Light light = this.calculateLight();
		Line line;

		if (!this.isStateInFinalPhase()) {
			light = Light.Green;
		}
		line = this.crossroad.getStreet(StreetDirection.East).getLine(4);
		this.setLineLight(line, light);
		line = this.crossroad.getStreet(StreetDirection.West).getLine(4);
		this.setLineLight(line, light);
	}

	@Override
	protected void updatePedestrianDisplay() {
		long pedTime = 0;
		PedestrianSemaphore.State state = State.Waiting;
		LightStateFactory factory = LightStateFactory.instance();
		long timeTaken = timeGained();
		if (this.counter >= this.initCounter + timeTaken - redPeriod) {
			pedTime = this.counter - (this.initCounter + timeTaken - redPeriod);
			state = State.Waiting;
		} else if (this.counter >= 0) {
			pedTime = this.counter;
			state = State.Crossing;

		} else {
			// if (this.counter <= 0)
			Direction.Vertical.setArrived(false);
			// XXX check if it works
			this.setArrivals(Direction.Vertical, false);

			pedTime = redPeriod + this.StreetCounter(Direction.Vertical)
					+ this.StreetCounter(Direction.Horizontal)
					- this.initCounter;
			state = State.Waiting;
		}

		PedestrianSemaphore semaphore = this.crossroad.getStreet(
				StreetDirection.North).getPedestrianSemaphore();
		semaphore.setState(state);
		semaphore.setTimeLeft(pedTime);

		semaphore = this.crossroad.getStreet(StreetDirection.South)
				.getPedestrianSemaphore();
		semaphore.setState(state);
		semaphore.setTimeLeft(pedTime);

		// update horizontal
		refreshArrivals(Direction.Horizontal);
		pedTime = redPeriod
				+ this.counter
				+ (factory
						.getLightState(LightStateDescriptor.VerticalLeftRight).initCounter + factory
						.getLightState(LightStateDescriptor.VerticalRightForward).initCounter)
				- (Direction.Horizontal.isArrived() ? factory
						.getLightState(LightStateDescriptor.VerticalLeftRight).maxTimeTaken
						+ factory
								.getLightState(LightStateDescriptor.VerticalRightForward).maxTimeTaken
						: 0);
		state = State.Waiting;

		semaphore = this.crossroad.getStreet(StreetDirection.West)
				.getPedestrianSemaphore();
		semaphore.setState(state);
		semaphore.setTimeLeft(pedTime);

		semaphore = this.crossroad.getStreet(StreetDirection.East)
				.getPedestrianSemaphore();
		semaphore.setState(state);
		semaphore.setTimeLeft(pedTime);
	}

	@Override
	protected void initializeState() {
		this.counter = this.initCounter
				+ timeGained();

	}

	@Override
	protected long timeGained() {
		LightStateFactory factory = LightStateFactory.instance();
		return factory.getLightState(LightStateDescriptor.HorizontalLeftRight).timeTaken
				+ factory
						.getLightState(LightStateDescriptor.HorizontalRightForward).timeTaken;
	}

}
